package test;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 
 * 
 * 模拟一个queue， mq
 * 
 * 
 * @author wesley.wei
 *
 */
public class MyQueue {
	
	private final int maxSize;
	
	private final int minSize = 0;
	
	//阻塞队列
	private LinkedList<Object > blockList = new LinkedList<>();
	
	//并发计数器
	private AtomicInteger count = new AtomicInteger(0);
	
	//锁
	private Object lock = new Object();
	
	public MyQueue(int maxsize) {
		this.maxSize = maxsize;
	}
	

	
	public Object get() throws InterruptedException {
		Object obj = null;
		synchronized (lock) {
			while (this.minSize == count.get()) {
				lock.wait();
			}
			obj = blockList.removeFirst();
			count.decrementAndGet();
			System.out.println("得到元素"+obj);
			lock.notify();
		}
		return obj;
	}
	
	
	
	public void add(Object obj) throws InterruptedException {
		synchronized (lock) {
			while (this.maxSize == count.get()) {
				System.out.println("queue已经满了，等待中...等待的元素"+obj);
				lock.wait();
			}
			
			blockList.add(obj);
			count.getAndIncrement();
			System.out.println("元素"+obj + "已经被添加");
			lock.notify();
		}
	}
	
	
	public int getCount() {
		return count.get();
	}
	
	
	
	public static void main(String[] args) throws InterruptedException {
		
		final MyQueue myQueue = new MyQueue(5);
		myQueue.add("1");
		myQueue.add("2");
		myQueue.add("3");
		myQueue.add("4");
		myQueue.add("5");
		
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					myQueue.add("6");
					myQueue.add("7");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"t1");
		
		
		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Object obj = myQueue.get();
					System.out.println("获取到元素"+obj);
					
					Thread.sleep(2);
					
					Object obj2 = myQueue.get();
					System.out.println("获取到元素"+obj2);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"t2");
		
		
		t1.start();
		TimeUnit.SECONDS.sleep(2);
		t2.start();
		
	}
	

}
